package com.spontaneapp;

import java.util.ArrayList;

import javax.crypto.spec.PSource;

import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.spontaneapp.adapters.NavDrawerListAdapter;
import com.spontaneapp.classes.NavDrawerItem;
import com.spontaneapp.fragments.AboutFragment;
import com.spontaneapp.fragments.FBLoginFragment;
import com.spontaneapp.fragments.HelpFragment;
import com.spontaneapp.fragments.HomeFragment;
import com.spontaneapp.fragments.InviteFriendsFragment;
import com.spontaneapp.fragments.MyPlacesFragment;
import com.spontaneapp.fragments.RateUsFragment;
import com.spontaneapp.fragments.SettingsFragment;

import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

public class MainActivity extends FragmentActivity {
	
	/*
	 * fragments IDs
	 */
	private static final int FBLogin = 8;
	private static final int HOME = 0;
	private static final int FRAGMENT_COUNT = 9;
	private int currFragment;
	
	private Fragment fragment;

	/*
	 * a flag to enable FB session state change checks
	 */
	private boolean isResumed = false;
	
	/*
	 * state to track the FB session and trigger a session state change listener
	 */
	private UiLifecycleHelper uiHelper;
	private Session.StatusCallback callback = 
	    new Session.StatusCallback() {
	    @Override
	    public void call(Session session, 
	            SessionState state, Exception exception) {
	        onSessionStateChange(session, state, exception);
	    }
	};
	
	/*
	 * Navigation Drawer state
	 */
	private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;

    // navigation drawer list items
    private String[] navMenuTitles;
    private TypedArray navMenuIcons;
 
    private ArrayList<NavDrawerItem> navDrawerItems;
    private NavDrawerListAdapter adapter;
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // Create an instance of the FB uiHelper and pass it the listener
        uiHelper = new UiLifecycleHelper(this, callback);
        uiHelper.onCreate(savedInstanceState);
        
        /*
         * Navigation Drawer setup
         */
        // load navigation drawer menu list items from strings.xml
        navMenuTitles = getResources().getStringArray(R.array.nav_drawer_list_titles);
        // load navigation drawer icons from resources from strings.xml
        navMenuIcons = getResources().obtainTypedArray(R.array.nav_drawer_list_icons);
 
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.nav_drawer_list_drawer);
        mDrawerList.setOnItemClickListener(new NavigationDrawerItemClickListener());
 
        navDrawerItems = new ArrayList<NavDrawerItem>();
        // add the navigation drawer items to the list
        for(int i = 0; i < 8; i++)
        	navDrawerItems.add(new NavDrawerItem(navMenuTitles[i], navMenuIcons.getResourceId(i, -1)));
        
        // Recycle the typed array
        navMenuIcons.recycle();
        
        // setting the navigation drawer list adapter
        adapter = new NavDrawerListAdapter(getApplicationContext(),navDrawerItems);
        mDrawerList.setAdapter(adapter);
        
        // enabling action bar app's icon and make it open and close navigation drawer
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);
 
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,R.drawable.ic_drawer,
                R.string.app_name, R.string.app_name){
            public void onDrawerClosed(View view) {
                // calling onPrepareOptionsMenu() to show action bar icons
                invalidateOptionsMenu();
            }
 
            public void onDrawerOpened(View drawerView) {
                // calling onPrepareOptionsMenu() to hide action bar icons
                invalidateOptionsMenu();
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        if (savedInstanceState == null) {
            // on first time display view for first navigation drawer item
        	showFragment(HOME, false);
        }
        
        currFragment = 1;

    }
    
    @Override
    public void onResume() {
        super.onResume();
        uiHelper.onResume();
        isResumed = true;
    }

    @Override
    public void onPause() {
        super.onPause();
        uiHelper.onPause();
        isResumed = false;
    }
    
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        uiHelper.onActivityResult(requestCode, resultCode, data);
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        uiHelper.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        uiHelper.onSaveInstanceState(outState);
    }
    
    @Override
    protected void onResumeFragments() {
        super.onResumeFragments();
        Session session = Session.getActiveSession();

        if (session != null && session.isOpened()) {
            // if the session is already open, try to show the Home fragment
            showFragment(HOME, false);
        } else {
            // otherwise present the login screen and ask the person to login.
            showFragment(FBLogin, false);
        }
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // toggle navigation drawer on selecting action bar app's icon/title - no need to do anything
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle action bar actions click
        switch (item.getItemId()) {
        case R.id.action_settings:
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }
    
    /***
     * Called when invalidateOptionsMenu() is triggered
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // if navigation drawer is opened, hide the action items, if closed, show them
        boolean isDrawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        menu.findItem(R.id.action_settings).setVisible(!isDrawerOpen);
        menu.findItem(R.id.action_map_view).setVisible(!isDrawerOpen);
        menu.findItem(R.id.action_add_new_place).setVisible(!isDrawerOpen);
        menu.findItem(R.id.action_list_view).setVisible(!isDrawerOpen);
        menu.findItem(R.id.action_report).setVisible(!isDrawerOpen);
        menu.setGroupVisible(R.id.action_always_visible,!isDrawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
    
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }
 
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Pass any configuration change to the drawer toggles
        mDrawerToggle.onConfigurationChanged(newConfig);
    }
    
    /**
     * Navigation Drawer item click listener subclass
     * gets the wanted fragment to the foreground
     * */
    private class NavigationDrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            // load the fragment for the selected navigation drawer item
        	showFragment(position, true);
        }
    }
	
	/**
	 * shows one fragment and hides the rest
	 * @param fragmentIndex - fragment to show
	 * @param addToBackStack - add current fragment to back stack or not
	 */
	private void showFragment(int position, boolean addToBackStack) {
		if(currFragment != position){
			FragmentManager fm = getSupportFragmentManager();
	        FragmentTransaction transaction = fm.beginTransaction();
		    switch (position) {
			case 0:
				fragment = new HomeFragment();
				break;
			case 1:
				fragment = new MyPlacesFragment();
				break;
			case 2:
				fragment = new SettingsFragment();
				break;
			case 3:
				fragment = new HelpFragment();
				break;
			case 4:
				fragment = new AboutFragment();
				break;
			case 5:
				fragment = new InviteFriendsFragment();
				break;
			case 6:
				fragment = new RateUsFragment();
				break;
			case 7:
				callFacebookLogout(getApplicationContext());
				return;
			case 8:
				currFragment = 0;
				fragment = new FBLoginFragment();
				break;
			default:
				return;
			}
	        transaction.replace(R.id.content_frame, fragment);
	        if (addToBackStack)
		        transaction.addToBackStack(null);
	        transaction.commit();
	        currFragment = position;
		}
		showHideNavDrawer(position);
	}
	
	/**
	 * Called due to FB login/logout session state changes.
	 * Shows the relevant fragment based on the session's state.
	 * 
	 */
	private void onSessionStateChange(Session session, SessionState state, Exception exception) {
	    // Only make changes if the activity is visible
	    if (isResumed) {
	        FragmentManager manager = getSupportFragmentManager();
	        // Get the number of entries in the back stack
	        int backStackSize = manager.getBackStackEntryCount();
	        // Clear the back stack
	        for (int i = 0; i < backStackSize; i++) {
	            manager.popBackStack();
	        }
	        if (state.isOpened()) {
	            // If the session state is open show the authenticated fragment
	            showFragment(currFragment, false);
	        } else if (state.isClosed()) {
	            // If the session state is closed show the login fragment
	            showFragment(FBLogin, false);
	        }
	    }
	}
	
	/**
	 * enable/disable the navigation drawer according to the current fragment - drawer disabled on login screen 
	 * @param fragmentIndex - index of the fragment we want to show
	 */
	private void showHideNavDrawer(int fragmentIndex){
		// login screen - disable drawer and home button
		if(FBLogin == fragmentIndex){
	    	mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
	    	mDrawerToggle.setDrawerIndicatorEnabled(false);
		    getActionBar().setDisplayHomeAsUpEnabled(false);
		    getActionBar().hide();
	    }
		// enable navigation drawer if it's disabled 
		else{
	    	if(mDrawerLayout.getDrawerLockMode(Gravity.LEFT) == DrawerLayout.LOCK_MODE_LOCKED_CLOSED){
	    		mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
	    		mDrawerToggle.setDrawerIndicatorEnabled(true);
	    		getActionBar().setDisplayHomeAsUpEnabled(true);
	    		getActionBar().show();
	    	}
	    	// update the selected item from the drawer and close it
	    	mDrawerList.setItemChecked(fragmentIndex, true);
	        mDrawerList.setSelection(fragmentIndex);
	        mDrawerLayout.closeDrawer(mDrawerList);
	    }
	}
	/*
	 * When the logout button in the nav drawer is pressed, logs out of FB and goes to login screen.
	 */
	public static void callFacebookLogout(Context context) {
	    Session session = Session.getActiveSession();
	    if (session != null) {
	        if (!session.isClosed()) {
	        	//clear your preferences if saved
	            session.closeAndClearTokenInformation();
	        }
	    } else {
	        session = new Session(context);
	        Session.setActiveSession(session);

	        //clear your preferences if saved
	        session.closeAndClearTokenInformation();
	    }
	}
    
}
